package com.jsh.erp.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONValidator;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.filter.Filter;
import com.alibaba.fastjson2.filter.ValueFilter;
import com.alibaba.fastjson2.writer.ObjectWriter;
import com.alibaba.fastjson2.writer.ObjectWriterProvider;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author jishenghua qq752718920  2018-10-7 15:26:27
 */
public class ExtJsonUtils {
    private static class NPFloatCodec implements ObjectWriter<Float> {
        public void write(JSONWriter serializer, Object object, Object fieldName, Type fieldType, long l)  {

            if (object == null) {
                if (serializer.isEnabled(JSONWriter.Feature.WriteNullNumberAsZero)) {
                    serializer.writeChar('0');
                } else {
                    serializer.writeNull();
                }
                return;
            }

            float floatValue = (Float) object;

            if (Float.isNaN(floatValue)) {
                serializer.writeNull();
            } else if (Float.isInfinite(floatValue)) {
                serializer.writeNull();
            } else {
                String floatText = Float.toString(floatValue);
                serializer.writeString(floatText);

                if (serializer.isEnabled(JSONWriter.Feature.WriteClassName)) {
                    serializer.writeChar('F');
                }
            }
        }
    }

    private static class NPDoubleSerializer implements ObjectWriter<Double> {
        @Override
        public void write(JSONWriter writer, Object object, Object fieldName, Type fieldType, long features) {
            if (object == null) {
                if (!writer.isEnabled(JSONWriter.Feature.WriteNullNumberAsZero)) {
                    writer.writeNull();
                } else {
                    writer.writeRaw('0'); // 直接写入数字 0
                }
                return;
            }

            double doubleValue = (Double) object;

            if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) {
                writer.writeNull();
            } else {
                writer.writeDouble(doubleValue); // 自动处理科学计数法和精度

                if (writer.isEnabled(JSONWriter.Feature.WriteClassName)) {
                    writer.writeRaw('D'); // 追加类型标记
                }
            }
        }
    }

    private static final String EXT_NAME = "ext";

    static class ExtFilter implements ValueFilter, Filter{
        static {
            ObjectWriter<Float> floatObjectWriter = new ObjectWriter<>() {
                @Override
                public void write(JSONWriter jsonWriter, Object o, Object o1, Type type, long l) {
                    if (o == null || Float.isNaN((Float) o) || Float.isInfinite((Float) o)) {
                        jsonWriter.writeNull();  // 处理 null 和非法值
                    } else {
                        jsonWriter.writeFloat((Float) o);  // 正常写入浮点数
                    }
                }
            };
            ObjectWriter<Double> doubleObjectWriter = new ObjectWriter<>() {
                @Override
                public void write(JSONWriter jsonWriter, Object o, Object o1, Type type, long l) {
                    if (o == null || Double.isNaN((Double) o) || Double.isInfinite((Double) o)) {
                        jsonWriter.writeNull();  // 处理 null 和非法值
                    } else {
                        jsonWriter.writeDouble((Double) o);  // 正常写入浮点数
                    }
                }
            };

            // 注册 Float 类型（同时处理 Float.class 和 float.class）
            JSON.register(Float.class, floatObjectWriter);
            JSON.register(float.class, floatObjectWriter); // 将基本类型指向包装类

            // 注册 Double 类型（同时处理 Double.class 和 double.class）
            JSON.register(Double.class, doubleObjectWriter);
            JSON.register(double.class, doubleObjectWriter);
        }

        private Map<Object, JSONObject> map = new HashMap<>();

        private Map<Object, Set<String>> ignoredKey = new HashMap<>();

        @Override
        public Object apply(Object object, String name, Object value) {
            if (name.equals(EXT_NAME) && value instanceof String) {
                map.put(object, JSON.parseObject((String) value));
                return false;
            }
            if (!map.containsKey(object)) {
                ignoredKey.put(object, new HashSet<String>());
            }
            ignoredKey.get(object).add(name);
//            if (value instanceof Float || value instanceof Double) {
//                if (!floatMap.containsKey(object)) {
//                    floatMap.put(object, new HashMap<String, Object>());
//                }
//                floatMap.get(object).put(name, value);
//                return false;
//            }
            return true;
        }

//        @Override
//        public void process(JSONWriter writer,Object object) {
//            if (map.containsKey(object)) {
//                Set<String> ignoredKeys;
//                if (ignoredKey.containsKey(object)) {
//                    ignoredKeys = ignoredKey.get(object);
//                } else {
//                    ignoredKeys = new HashSet<>();
//                }
//                for (Map.Entry<String, Object> entry : map.get(object).entrySet()) {
//                    if (!ignoredKeys.contains(entry.getKey())) {
//                        writeKeyValue(entry.getKey(), entry.getValue());
//                    }
//                }
//            }
//        }
    }

    public static String toJSONString(Object object) {
        return JSON.toJSONString(object, new ExtFilter());
    }

    public interface ExtExtractor {
        String getExt(Object bean);
    }
}
